package com.xingchi.tornado.storage.core;

import com.xingchi.tornado.storage.core.model.dto.FileChunkMergeDTO;
import com.xingchi.tornado.storage.core.model.dto.FileChunkUploadDTO;
import com.xingchi.tornado.storage.core.model.vo.FileChunkUploadVO;

import java.io.FileNotFoundException;
import java.io.InputStream;
import java.nio.file.Path;
import java.util.function.Supplier;

/**
 * 文件存储服务
 *
 * @author xingchi
 * @date 2024/4/8 21:35
 */
public interface FileStorageService {

    /**
     * 文件上传
     *
     * @param filePath 文件的存储路径，在本机上的文件存储路径
     * @return 文件在文件存储服务器上的路径唯一标识，在云存储中返回文件的对象名
     * @throws FileNotFoundException 文件不存在
     */
    String uploadFile(String filePath) throws FileNotFoundException;

    /**
     * 文件上传
     *
     * @param filePath 文件存储路径
     * @return 文件在文件存储服务器上的路径唯一标识，在云存储中返回文件的对象名
     */
    String uploadFile(Path filePath) throws FileNotFoundException;

    /**
     * 根据文件的字节上传文件
     *
     * @param bytes    文件的字节
     * @param fileName 文件的完整名称
     * @return 文件在文件存储服务器上的路径唯一标识，在云存储中返回文件的对象名
     */
    String uploadFile(byte[] bytes, String fileName);

    /**
     * 获取分片文件在服务器上的存储路径
     *
     * @param sha256 文件的唯一标识
     * @return 文件的分片存储路径
     */
    String getChunkPath(String sha256);

    /**
     * 根据文件的输入流上传文件
     *
     * @param is       文件的输入流
     * @param fileName 文件的完整名称
     * @return 文件在文件存储服务器上的路径唯一标识，在云存储中返回文件的对象名
     */
    String uploadFile(InputStream is, String fileName);

    /**
     * 根据文件在文件服务器上的存储路径获取文件对应的字节书，注意文件过大可能会导致内存溢出问题
     *
     * @param path 文件的存储路径
     * @return 文件字节
     */
    byte[] getFileBytes(String path);

    /**
     * 根据文件路径获取文件流
     *
     * @param path  文件路径
     * @return      文件流
     */
    InputStream getInputStream(String path);

    /**
     * 删除文件
     *
     * @param path 文件的存储路径
     */
    void deleteFile(String path);

    /**
     * 获取文件的访问url
     *
     * @param path 文件的存储路径，在云存储中则为对应的对象名称
     * @return url
     */
    default String getUrl(String path) {
        return path;
    }

    /**
     * 检查分片上传状态
     *
     * @param fileChunkUpload 分片信息
     * @return 分片上传结果
     */
    FileChunkUploadVO checkChunkUpload(FileChunkUploadDTO fileChunkUpload);

    /**
     * 上传分片
     *
     * @param fileChunkUpload 分片信息
     * @return 分片上传结果
     */
    String uploadChunk(FileChunkUploadDTO fileChunkUpload);

    /**
     * 合并分片
     *
     * @param info 分片信息
     * @return 最终的文件URL
     */
    String mergeChunks(FileChunkMergeDTO info, Supplier<FileChunkUploadVO> supplier);
}
